
// 注意，这里的 x 是个引用变量，用来存放 堆区 中一个实例的地址
let x = {
    name: '张君宝' ,
    introduce: function(){
        console.log( '我是' , this.name );
    },
    add: function( a , b ) {
        console.log( `${this.name}正在计算${a}+${b}`  );
        let c = a + b ;
        console.log( `${this.name}计算出${a}+${b}的结果是${c}` );
        return c ;
    }
}

// 默认情况下，在 introduce 内部的 this 表示当前实例
// 即在 introduce() 之前 的 . 之前的 x 变量所引用的实例
x.introduce();
// 默认情况下，在 add 内部的 this 表示当前实例
// 即在 add() 之前 的 . 之前的 x 变量所引用的实例
x.add( 2 , 7 );

console.log( '- - - - - - - - - - - - - - - - - - - - -' );

let y = {
    name: '杨过'
}

let z = {
    name: '周伯通'
}

// 此时的 x 相当于一个命名空间，通过 这个命名空间可以找到 introduce 函数
// functionReference.call( thisArg , ...params )
// 其中 thisArg 表示在 functionReference 对应的函数内部使用 this 时表示哪个实例
x.introduce.call( y ); // Function.prototype.call
x.introduce.call( z );

x.add.call( y , 6 , 8 );
x.add.call( z , 7 , 5 );

console.log( '- - - - - - - - - - - - - - - - - - - - -' );

// functionReference.apply( thisArg , paramArray )
let params = [ 14 , 28 ];
x.add.apply( y , params ); // Function.prototype.apply
x.add.apply( z , params );

console.log( '- - - - - - - - - - - - - - - - - - - - -' );

let another = x.add.bind( y , 55 , 65 );
another();

another = x.add.bind( z ); // Function.prototype.bind
another( 120 , 110 );

console.log( '- - - - - - - - - - - - - - - - - - - - -' );

console.log( x.add.toString() ); // Function.prototype.toString